#!/bin/bash
# Reservar_A.sh
# comando para procesar solicitudes de reservas

# CONSTANTES
MSJ_INICIO='Inicio de Reservar_A. Cantidad de archivos de entrada:'
MSJ_PROCESAMIENTO='Archivo a procesar:'
MSJ_RECHAZO_ARCHIVO='Se rechaza el archivo. Motivo:'
MSJ_RECHAZO_SOLICITUD='Se rechaza la solicitud. Motivo:'

# VARIABLES GLOBALES
MOTIVO_RECHAZO=''
ID_OBRA_SALA=0
RESERVA_POR_OBRA=1
ARCH_COMBO=''
LINEA_COMBO=''
EVENTO_EXISTE=0
RESERVAS_ACEPTADAS=0
RESERVAS_RECHAZADAS=0

# TODO no hardcodear esto
GRUPO_ROOT="$GRUPO"
#GRUPO_ROOT="/home/marcosrimoldi/tpSO/sogrupo112013/"
ARCHIVO_LOG="Reservar_A"

# TODO commentar esto porque son variables de entorno
#ACEPDIR='../ACEPDIR'
#PROCDIR='../PROCDIR'
#RECHDIR='../RECHDIR'
#MAEDIR='../MAEDIR'

OBRAS="$MAEDIR/obras.mae"
SALAS="$MAEDIR/salas.mae"
RESERVASOK="$PROCDIR/reservas.ok"
RESERVASNOK="$PROCDIR/reservas.nok"
 
# Funcion para escribir el inicio rechazo en el log con su motivo
function loguear() {
 # I, E, W, SE
 local tipoLog=$1
 local mensaje=$2
 local param=$3
 #echo "$tipoLog $mensaje $param";
 $GRUPO_ROOT/Grabar_L.sh "$ARCHIVO_LOG" "$tipoLog" "$mensaje $param";
}

function obtenerFechaFuncion() {
 solicitud=$1
 #echo $solicitud | grep -o "[0-9]\{2\}/[0-9]\{2\}/[0-9]\{4\}"
 solicitante=$(obtenerEnArray "$solicitud" 1 ";") # CAMBIO
 echo $solicitante
}

function obtenerHoraFuncion() {
 solicitud=$1
 #echo $solicitud | grep -o "[0-9]\{2\}:[0-9]\{2\}"
 solicitante=$(obtenerEnArray "$solicitud" 2 ";") # CAMBIO
 echo $solicitante
}

function obtenerIdObra() {
 local idObra=$(obtenerEnArray "$LINEA_COMBO" 1 ";")
 echo $idObra
}

function obtenerNombreObra() {
 idObra=$1
 local nombre=""
 id=0
 while read obra
  do
   id=$(obtenerEnArray "$obra" 0 ";")
   if [ $idObra -eq $id ]
    then
     nombre=$(obtenerEnArray "$obra" 1 ";")
     break
   fi
 done < $OBRAS

 echo $nombre
}

function obtenerIdSala() {
 local idSala=$(obtenerEnArray "$LINEA_COMBO" 4 ";")
 echo $idSala
}

function obtenerNombreSala() {
 idSala=$1
 local nombre=''
 while read sala; 
  do
   id=$(obtenerEnArray "$sala" 0 ";")
   if [ $idSala -eq $id ]
    then
     nombre=$(obtenerEnArray "$sala" 1 ";")
     break
   fi
 done < $SALAS

 echo $nombre
}

function obtenerButacasSolicitadas() {
 #TODO No estoy contemplando si el ultimo campo de la solicitud esta presente o no (SECCION es opcional)
 # podria ver si el ultimo campo tiene letras entonces esta presente el campo REQUISITOS, sino el ultimo campo es el de las butacas
 solicitud=$1
 cantidadSolicitada=$(obtenerAnteUltimoCampo $solicitud ";")
 echo $cantidadSolicitada
}

function obtenerIdCombo() {
 idCombo=$(obtenerEnArray "$LINEA_COMBO" 0 ";")
 echo $idCombo
}

function obtenerSolicitante() {
 solicitud=$1
 #TODO Primer campo pero que no tenga formato fecha porque el campo solicitante es opcional
 solicitante=$(obtenerEnArray "$solicitud" 0 ";")
 echo $solicitante
}

function obtenerFila() {
 local solicitud=$1
 local filaSolicitada=$(obtenerEnArray "$solicitud" 3 ";")
 echo $filaSolicitada
}

function obtenerButaca() {
 local solicitud=$1
 local butSolicitada=$(obtenerEnArray "$solicitud" 4 ";")
 echo $butSolicitada
}

function obtenerSeccion() {
 # CAMBIO
 #local solicitud=$1
 local solicitud=$(echo $1 | tr -d '\n\r')
 #solicitud=$(echo $1 | tr -d '\r')
 #local seccion=$(obtenerUltimoCampo "$solicitud" ";")
 local seccion=$(obtenerEnArray "$solicitud" 6 ";")
 echo $seccion
}

function obtenerEmailSolicitante() {
 local archivoProcesado=$1

 local nombreBase=$(basename $archivoProcesado)

 local emailSolicitante=$(obtenerEnArray "$nombreBase" 1 "-")
 echo $emailSolicitante
}

function obtenerEnArray() {
   ENTRADA=$1
   indice=$2
   separador=$3

   OIFS="$IFS" #backup IFS
   IFS="$separador"
   read -a array <<< "${ENTRADA}"

   tamanio=${#array[@]}

   if [ $indice -lt $tamanio ]
     then
       echo "${array[$tamanio-$tamanio+$indice]}"
     else
       echo ""
   fi

   IFS="$OIFS" #restore IFS
}


function obtenerAnteUltimoCampo() {
   ENTRADA=$1
   separador=$2

   OIFS="$IFS" #backup IFS
   IFS="$separador"
   read -a array <<< "${ENTRADA}"

   tamanio=${#array[@]}
   echo "${array[$tamanio-2]}"

   IFS="$OIFS" #restore IFS
}

function obtenerUltimoCampo() {
   ENTRADA=$1
   separador=$2

   OIFS="$IFS" #backup IFS
   IFS="$separador"
   read -a array <<< "${ENTRADA}"

   tamanio=${#array[@]}
   echo "${array[$tamanio-1]}"

   IFS="$OIFS" #restore IFS
}


function archivoExiste() {
 local archivo=$1;
 if [ -e "$archivo" ]
 then
  return 1;
 else
  return 0;
 fi
}

function archivoVacio() {
  [ -s $1 ]
}

function validarFormatoFecha() {
	FECHA=$1
	LARGO=${#FECHA};
	if [ $LARGO -ne 10 ]; 
		then return 0;
	fi
	d=${FECHA:0:2}; 
	m=${FECHA:3:2}; 
	a=${FECHA:6:4}; 
	if date -d "$a-$m-$d";
		then return 1;
		else return 0;
	fi 
}

function esFechaMayorIgual() {
	if [ $2 -ge $1 ]; 
		then return 1;
		else return 0;
	fi
}

function esFechaMayor() {
	if [ $2 -gt $1 ]; 
		then return 1;
		else return 0;
	fi
}

function validarRangoFecha() {
	RANGO45=$(date --date='45 days' +"%Y%m%d");
	esFechaMayorIgual $1 $RANGO45
	if [ $? -ne 0 ];
	   then return 1;
	   else return 0;
	fi
}

function validarVigenciaFecha() {
	HOY=$(date -d today +"%Y%m%d")
	esFechaMayor $HOY $1 
	if [ $? -ne 0 ];
	   then return 1;
	   else return 0;
	fi
}

function validarFechaReserva() {
	validarFormatoFecha $1 
	if [ $? -ne 1 ];
	  then 
	   MOTIVO="Formato de fecha invalida." # CAMBIO
	   return 0;
	fi
	
	FECHA=$1
	d=${FECHA:0:2}; 
	m=${FECHA:3:2}; 
	a=${FECHA:6:4}; 

	RESERVA=$(date -d "$a-$m-$d" +"%Y%m%d");
	
	validarVigenciaFecha $RESERVA 
	if [ $? -ne 1 ];
	  then
    	   MOTIVO="Reserva vencida."
	   return 0;
	fi
	
	validarRangoFecha $RESERVA
	if [ $? -ne 1 ];
	  then 
           MOTIVO="Reserva anticipada."
	   return 0;
	fi
	
	return 1;
}

function validatFormatoHora() {
	pattern="(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$"

	if [[ $1 =~ $pattern ]]
	  then 
	    return 1;
	fi
	MOTIVO="Hora invalida."
	return 0;
}

function validarArchivo() {

 archivo=$1
 nombre=$(basename $archivo)

 archivoExiste "$PROCDIR/$nombre"
 if [ $? -eq 1 ]
  then
   MOTIVO="El archivo esta duplicado y ya se encuentra en la carpeta de procesados."
   return 0
 fi

 archivoVacio $archivo
 if [ $? -eq 1 ]
  then
   MOTIVO="El archivo esta vacio."
   return 0
 fi

 # TODO validarFormato del registro ?

 # obtener el ID del comienzo del archivo hasta el primer guion y chequear si por Obra o Sala. El nombre fue validado en Recibir_A.sh
 #ID_OBRA_SALA=$(echo ${nombre%-*})
 ID_OBRA_SALA=$(obtenerEnArray "$nombre" 0 "-")
 resto=$(($ID_OBRA_SALA%2))
 
 if [ $resto -eq 0 ];
   then
     RESERVA_POR_OBRA=0
   else
     RESERVA_POR_OBRA=1
 fi

 return 1
}


function rechazarArchivo() {

 loguear "I" "$MSJ_RECHAZO_ARCHIVO" "$MOTIVO"

 Mover_A.sh "$1" "$RECHDIR/" &

 $GRUPO_ROOT/Grabar_L.sh "$ARCHIVO_LOG" "I" "Se movio archivo $1 a la carpeta $RECHDIR" -p:Mover_A
}


function obtenerButacasDisponibles() {
 local combo=$1
 local disponibles=$(obtenerAnteUltimoCampo $combo ";")
 echo $disponibles
}


function obtenerRequisitos() {
 local combo=$1
 local requisitos=$(obtenerUltimoCampo $combo ";")
 echo $requisitos
}


# Funcion que valida la disponibilidad de butacas, retorna 1 si hay disponibilidad
# Parametros: registroCombo, solicitud
function validarDisponibilidad() {
  #echo "Ejecutando: validarDisponibilidad()"
  registroCombo=$1
  solicitud=$2

  cantidadDisponible=$(obtenerButacasDisponibles $registroCombo)
  #echo "cantidad disponible: "$cantidadDisponible

  cantidadSolicitada=$(obtenerButacasSolicitadas $solicitud)
  #echo "cantidad solicitada: "$cantidadSolicitada

  if [ $cantidadSolicitada -le $cantidadDisponible ]
    then
      return 1
  fi
  return 0
}


# Funcion que busca si el evento existe, si existe verifica disponibilidad y si ambas son true entonces retorna 1, sino 0
# Parametros: solicitud
function validarEventoYDisponibilidad() {

  local solicitud=$1
  fecha=$(obtenerFechaFuncion $solicitud)
  hora=$(obtenerHoraFuncion $solicitud)

  regex=''
  
  if [ $RESERVA_POR_OBRA -eq 1 ] 
    then
       regex='^\([A-Za-z0-9]\+;'$ID_OBRA_SALA';'$fecha';'$hora';.*\)'
       #echo 'busqueda por ID_OBRA + FECHA + HORA'
    else
       regex='^\([A-Za-z0-9]\+;[A-Za-z0-9]\+;'$fecha';'$hora';'$ID_OBRA_SALA';.*\)'
       #echo 'busqueda por ID_SALA + FECHA + HORA'
  fi

  for archivo_combo in "$PROCDIR/combos.dis"
  do
   while read lineaCombo
   do
     #echo 'LINEA DE ARCHIVO DE COMBOS' $lineaCombo
     #echo "--------------MATCHEO------------------"
     existe_evento=$(echo "$lineaCombo" | grep -c "$regex")

     if [ $existe_evento -ne 0 ]
       # Entonces existe el evento
       then
	#echo "EXISTE EL EVENTO!"
        ARCH_COMBO=$archivo_combo
        LINEA_COMBO=$lineaCombo
        EVENTO_EXISTE=1

        validarDisponibilidad $lineaCombo $solicitud
  
        if [ $? -ne 0 ];
	  then
            #echo "HAY DISPONIBILIDAD!"
            return 1
          else
            #echo "NO HAY DISPONIBILIDAD!"
            MOTIVO="No hay disponibilidad."
            return 0
        fi
     fi

     #echo "--------------FIN MATCHEO------------------"
   done < $archivo_combo
  done
 
  EVENTO_EXISTE=0
  MOTIVO="El evento solicitado no existe."
  return 0
}


# Funcion que valida la fecha de una solicitd
# Parametros: solicitud
function validarSolicitud() {

  local solicitud=$1
  validarFechaReserva "$(obtenerFechaFuncion $solicitud)"

  if [ $? -ne 1 ]
   then
     #echo "FECHA INVALIDA."
     return 0
  fi

  validatFormatoHora "$(obtenerHoraFuncion $solicitud)"

  if [ $? -ne 1 ]
   then
     #echo "HORA INVALIDA."
     return 0
  fi

  #echo "FECHA Y HORA VALIDAS."
  return 1
}


# Funcion que arma un registro de reserva aceptada
# Parametros: solicitud, archivo siendo procesado
function crearReserva() {
  # Asumo que todos los campos del archivo de Combos son obligatorios

  local solicitud=$1
  local archivoProcesado=$2

  local idObra=$(obtenerIdObra)
  local nombreObra=$(obtenerNombreObra $idObra)
  local fechaFuncion=$(obtenerFechaFuncion $solicitud)
  local horaFuncion=$(obtenerHoraFuncion $solicitud)
  local idSala=$(obtenerIdSala)
  local nombreSala=$(obtenerNombreSala $idSala)
  local butacasConf=$(obtenerButacasSolicitadas $solicitud)
  local idCombo=$(obtenerIdCombo)
  local solicitante=$(obtenerSolicitante $solicitud)  
  local emailSolicitante=$(obtenerEmailSolicitante $archivoProcesado)  
  local usuario="$(whoami)"
  local fechaGrabacion=$(date +"%d/%m/%y %R")

  #butacas solicitadas es igual a confirmadas

  echo $idObra";"$nombreObra";"$fechaFuncion";"$horaFuncion";"$idSala";"$nombreSala";"$butacasConf";"$idCombo";"$solicitante";"$butacasConf";"$emailSolicitante";"$usuario";"$fechaGrabacion
}


# Funcion que actualiza butacas disponibles en archivo de Combos
# Parametros: solicitud
function actualizarDisponibilidad() {
  local solicitud=$1 
  local butacas=$(obtenerButacasSolicitadas $solicitud)
  local disponibles=$(obtenerButacasDisponibles $LINEA_COMBO)
  local requisitos=$(obtenerRequisitos $LINEA_COMBO)

  local cadena=$disponibles";"$requisitos

  local nuevoDisponible=$(expr $disponibles - $butacas)

  local cadena2=$nuevoDisponible";"$requisitos

  local lineaReemplazo=$(echo $LINEA_COMBO | sed "s/$cadena/$cadena2/g")

  #echo $lineaReemplazo
  
  local lineaOriginalEscapeada=$(echo $LINEA_COMBO | sed 's/\//\\\//g')
  local lineaReemplazoEscapeada=$(echo $lineaReemplazo | sed 's/\//\\\//g')

  sed -i "s/$lineaOriginalEscapeada/$lineaReemplazoEscapeada/g" $ARCH_COMBO

  loguear "I" "Actualización del archivo de disponibilidad:" "Disponibilidad anterior: $disponibles Disponibilidad actual: $nuevoDisponible"

}


# Funcion que acepta una reserva, actualizando butacas disponibles y grabando la reservas en reservas.ok
# Parametros: solicitud a aceptar, archivo siendo preocesado
function aceptarReserva() {
  local solicitud=$1
  local archivoProcesado=$2

  actualizarDisponibilidad $solicitud

  local reserva=$(crearReserva $solicitud $archivoProcesado)

  echo $reserva >> $RESERVASOK
  
  ((RESERVAS_ACEPTADAS++))
}


# Funcion que arma un registro de rechazo
# Parametros: solicitud a rechazar, archivo siendo preocesado
function crearReservaRechazada() {
  #solicitante;fecha_funcion;hora_funcion;fila;butaca;cant_butacas_solic;seccion;motivo;id_sala;id_obra;email_solic;usuario;fecha_grabacion
  local solicitud=$1
  local archivoProcesado=$2
  local solicitante=$(obtenerSolicitante $solicitud)  
  local fechaFuncion=$(obtenerFechaFuncion $solicitud)
  local horaFuncion=$(obtenerHoraFuncion $solicitud)

  local filaSolicitada=$(obtenerFila $solicitud)
  local butacaSolicitada=$(obtenerButaca $solicitud)
  
  local butacas=$(obtenerButacasSolicitadas $solicitud)

  local seccionSolicitada=$(obtenerSeccion "$solicitud") #CAMBIO
  # MOTIVO

  if [ $EVENTO_EXISTE -eq 1 ]
   then
    local idSala=$(obtenerIdSala)
    local idObra=$(obtenerIdObra)
  fi

  local emailSolicitante=$(obtenerEmailSolicitante $archivoProcesado)  

  local usuario="$(whoami)"
  local fechaGrabacion=$(date +"%d/%m/%y %R")

  echo $solicitante";"$fechaFuncion";"$horaFuncion";"$filaSolicitada";"$butacaSolicitada";"$butacas";"$seccionSolicitada";"$MOTIVO";"$idSala";"$idObra";"$emailSolicitante";"$usuario";"$fechaGrabacion
}


# Funcion que rechaza una solicitud de reserva
# Parametros: solicitud a rechazar
function rechazarReserva() {

  local solicitud=$1
  local archivoProcesado=$2
  local reserva=$(crearReservaRechazada "$solicitud" $archivoProcesado) #CAMBIO
  loguear "I" "$MSJ_RECHAZO_SOLICITUD" "$MOTIVO"

  echo $reserva >> $RESERVASNOK
  ((RESERVAS_RECHAZADAS++))

}


# Funcion que procesa un registro de solicitud
# Parametros: solicitud a procesar, archivo siendo procesado
function procesarSolicitud() {

 solicitud=$1
 local archivoProcesado=$2

 validarSolicitud $solicitud
 
 if [ $? -ne 0 ];
   then
     validarEventoYDisponibilidad $solicitud
     if [ $? -ne 0 ];
       then
	 #echo "SOLICITUD A ACEPTAR:" $solicitud
         #echo "EVENTO SOLICITADO:" $LINEA_COMBO
         #echo "EVENTO EN EL ARCHIVO:" $ARCH_COMBO
	 aceptarReserva $solicitud $archivoProcesado
       else
         rechazarReserva "$solicitud" $archivoProcesado # CAMBIO
     fi
   else
     rechazarReserva "$solicitud" $archivoProcesado # CAMBIO
   fi
}


# Funcion que recorre los registros de un archivo y procesa las solicitudes
# Parametros: archivo a procesar
function procesarArchivo() {

 RESERVAS_ACEPTADAS=0
 RESERVAS_RECHAZADAS=0
 
 while read p; do
  #echo 'SOLICITUD A PROCESAR: ' $p
  procesarSolicitud "$p" $1 # CAMBIO
 done < $1

 Mover_A.sh "$1" "$PROCDIR/" &

 $GRUPO_ROOT/Grabar_L.sh "$ARCHIVO_LOG" "I" "Se movio archivo $1 a la carpeta $PROCDIR" -p:Mover_A

 loguear "I" "CANTIDAD DE RESERVAS CONFIRMADAS:" "$RESERVAS_ACEPTADAS"
 loguear "I" "CANTIDAD DE RESERVAS RECHAZADAS:" "$RESERVAS_RECHAZADAS"
}


# Funcion que recorre el directorio ACEPDIR y procesa sus archivos
# Parametros: ninguno
function leerArchivosAceptados() {
 
 loguear "I" "$MSJ_INICIO" $(ls -1 "$ACEPDIR" | wc -l)

 # Enable nullglob por si no hay archivo en la carpeta CAMBIO
 shopt -s nullglob

 for archivo in "$ACEPDIR"/*
 do
   # Disable nullglob por las dudas CAMBIO
   shopt -u nullglob

   loguear "I" "$MSJ_PROCESAMIENTO""$archivo"
   validarArchivo $archivo
   
   if [ $? -ne 0 ];
   then
     procesarArchivo $archivo
   else
     rechazarArchivo $archivo
   fi
 done

 loguear "I" "Fin de Reservar_A" ""
}

leerArchivosAceptados
